import 'package:flutter/foundation.dart';
import 'package:audioplayers/audioplayers.dart';
import '../services/tts_service.dart';

enum TTSState {
  idle,
  loading,
  playing,
  paused,
  error,
}

class TTSProvider extends ChangeNotifier {
  final TTSService _ttsService;
  final AudioPlayer _audioPlayer;
  
  TTSState _state = TTSState.idle;
  String? _currentAudioUrl;
  String? _errorMessage;
  Map<String, String> _ttsCache = {};

  TTSProvider({
    TTSService? ttsService,
    AudioPlayer? audioPlayer,
  })  : _ttsService = ttsService ?? TTSService(),
        _audioPlayer = audioPlayer ?? AudioPlayer() {
    _initializeAudioPlayer();
  }

  TTSState get state => _state;
  String? get errorMessage => _errorMessage;

  void _initializeAudioPlayer() {
    _audioPlayer.onPlayerComplete.listen((_) {
      _state = TTSState.idle;
      notifyListeners();
    });

    _audioPlayer.onPlayerStateChanged.listen((PlayerState state) {
      switch (state) {
        case PlayerState.playing:
          _state = TTSState.playing;
          break;
        case PlayerState.paused:
          _state = TTSState.paused;
          break;
        case PlayerState.stopped:
        case PlayerState.completed:
          _state = TTSState.idle;
          break;
        default:
          break;
      }
      notifyListeners();
    });
  }


  Future<void> playText(String text) async {
    if (_state == TTSState.loading) {
      return;
    }

    // Check cache first
    if (_ttsCache.containsKey(text)) {
      await _playAudio(_ttsCache[text]!);
      return;
    }

    _state = TTSState.loading;
    _errorMessage = null;
    notifyListeners();

    try {
      final response = await _ttsService.generateSpeech(text);
      
      if (response.isSuccess && response.audioFiles.isNotEmpty) {
        final audioUrl = response.audioFiles.first.url;
        _ttsCache[text] = audioUrl;
        await _playAudio(audioUrl);
      } else {
        throw TTSException(response.msg);
      }
    } catch (e) {
      _state = TTSState.error;
      _errorMessage = e.toString();
      notifyListeners();
    }
  }

  Future<void> _playAudio(String url) async {
    try {
      _currentAudioUrl = url;
      await _audioPlayer.play(UrlSource(url));
      _state = TTSState.playing;
      notifyListeners();
    } catch (e) {
      _state = TTSState.error;
      _errorMessage = 'Failed to play audio: $e';
      notifyListeners();
    }
  }

  Future<void> pauseAudio() async {
    if (_state == TTSState.playing) {
      await _audioPlayer.pause();
      _state = TTSState.paused;
      notifyListeners();
    }
  }

  Future<void> resumeAudio() async {
    if (_state == TTSState.paused) {
      await _audioPlayer.resume();
      _state = TTSState.playing;
      notifyListeners();
    }
  }

  Future<void> stopAudio() async {
    await _audioPlayer.stop();
    _state = TTSState.idle;
    _currentAudioUrl = null;
    notifyListeners();
  }

  void clearCache() {
    _ttsCache.clear();
  }

  Future<void> preloadText(String text) async {
    if (_ttsCache.containsKey(text)) {
      return;
    }

    try {
      final response = await _ttsService.generateSpeech(text);
      if (response.isSuccess && response.audioFiles.isNotEmpty) {
        _ttsCache[text] = response.audioFiles.first.url;
      }
    } catch (e) {
      print('Failed to preload text: $e');
    }
  }

  Future<void> preloadTexts(List<String> texts) async {
    for (final text in texts) {
      await preloadText(text);
    }
  }

  @override
  void dispose() {
    _audioPlayer.dispose();
    _ttsService.dispose();
    super.dispose();
  }
}